package cn.jslancer.webx.router;

import cn.jslancer.webx.exception.WebxException;
import cn.jslancer.webx.request.ServerRequest;
import io.netty.handler.codec.http.HttpMethod;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author jslancer
 * @date 2018/7/29 21:26
 */
public class RouterImpl implements Router {

    private Map<String, Route> map = new ConcurrentHashMap<>();



    private final AtomicInteger orderSequence = new AtomicInteger(0);

    private Set<Route> routes = new ConcurrentSkipListSet<>();


    @Override
    public void accept(RoutingContext context) {
        ServerRequest request = context.request();
        String path = request.getPath();
        RouteImpl route = (RouteImpl) map.get(path);
        if (route == null) {
            throw new WebxException("path = " + path + " not match");
        }

        route.handleContext(context);
    }

    @Override
    public List<Route> routes() {
        return new ArrayList<>(routes);
    }

    @Override
    public Route route() {
        return new RouteImpl(this, orderSequence.getAndIncrement());
    }

    @Override
    public Route route(HttpMethod method, String path) {
        return new RouteImpl(this, orderSequence.getAndIncrement(), method, path);
    }

    @Override
    public Route route(String path) {
        return new RouteImpl(this, orderSequence.getAndIncrement(), path);
    }

    //region GET 路由

    @Override
    public Route get() {
        return route().method(HttpMethod.GET);
    }

    @Override
    public Route get(String path) {
        return route(HttpMethod.GET, path);
    }

    //endregion

    //region POST 路由

    @Override
    public Route post() {
        return route().method(HttpMethod.POST);
    }

    @Override
    public Route post(String path) {
        return route(HttpMethod.POST, path);
    }

    //endregion

    //region HEAD 路由

    @Override
    public Route head() {
        return route().method(HttpMethod.HEAD);
    }

    @Override
    public Route head(String path) {
        return route(HttpMethod.HEAD, path);
    }

    //endregion

    //region OPTIONS 路由

    @Override
    public Route options() {
        return route().method(HttpMethod.OPTIONS);
    }

    @Override
    public Route options(String path) {
        return route(HttpMethod.OPTIONS, path);
    }

    //endregion

    //region PUT 路由

    @Override
    public Route put() {
        return route().method(HttpMethod.PUT);
    }

    @Override
    public Route put(String path) {
        return route(HttpMethod.PUT, path);
    }

    //endregion

    //region DELETE 路由

    @Override
    public Route delete() {
        return route().method(HttpMethod.DELETE);
    }

    @Override
    public Route delete(String path) {
        return route(HttpMethod.DELETE, path);
    }

    //endregion

    //region PATCH 路由

    @Override
    public Route patch() {
        return route().method(HttpMethod.PATCH);
    }

    @Override
    public Route patch(String path) {
        return route(HttpMethod.TRACE, path);
    }

    //region TRACE 路由

    @Override
    public Route trace() {
        return route().method(HttpMethod.TRACE);
    }

    @Override
    public Route trace(String path) {
        return route(HttpMethod.TRACE, path);
    }

    //endregion

    //region CONNECT 路由

    @Override
    public Route connect() {
        return route().method(HttpMethod.CONNECT);
    }

    @Override
    public Route connect(String path) {
        return route(HttpMethod.CONNECT, path);
    }

    //endregion

    public void addRoute(Route route) {
        this.routes.add(route);
    }

    public void addRoute(String path, Route route) {
        this.map.put(path, route);
    }
}
